package switchviz.core.scenario;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.swing.Timer;

import org.apache.log4j.Logger;

import switchviz.core.data.TimeStamp;
import switchviz.core.view.View;
import switchviz.core.view.ViewEventListener;
import switchviz.graphic.GraphicsFrame;
import switchviz.network.NetworkException;
import switchviz.network.netswitch.Switch;
import switchviz.recording.Record;
import switchviz.recording.Replay;

public class Scenario implements ActionListener, WindowListener 
{
	private View _view = null;
	private Switch _switch = null;
	private GraphicsFrame _gf = null;
	private ScenarioDataModel _dm = null;
	private ViewEventListener _vel = null;
	private Timer _timer = null;
	private Record _record = null;
	private Replay _replay = null;
	private static Logger logger = Logger.getLogger(Scenario.class);
	
	public Scenario(View view, Switch netswitch, ScenarioDataModel scenariodatamodel, Record record, Replay replay)
	{
		this._view = view;
		this._switch = netswitch;
		this._replay = replay;
		setScenarioModel(scenariodatamodel);
		setRecord(record);
		this._timer = new Timer(getScenarioModel().getTimeintervall(), this);
	}
	
	public Scenario(View view, Switch netswitch, ScenarioDataModel scenariodatamodel, Record record)
	{
		this(view, netswitch, scenariodatamodel, record, null);
	}
	
	public Scenario(View view, Switch netswitch, ScenarioDataModel scenariodatamodel)
	{
		this(view, netswitch, scenariodatamodel, null, null);
	}
	
	public Scenario(View view, ScenarioDataModel scenariodatamodel, Replay replay)
	{
		this(view, null, scenariodatamodel, null, replay);
	}
	
	public ScenarioDataModel getScenarioModel()
	{
		if(_dm == null)
			_dm = new ScenarioDataModel();
		return _dm;
	}
	
	public View getView()
	{
		return _view;
	}
	
	public Switch getSwitch()
	{
		return _switch;
	}
	
	public Replay getReplay()
	{
		return _replay;
	}
	
	private Record getRecord()
	{
		return _record;
	}
	
	private void setScenarioModel(ScenarioDataModel dm)
	{
		this._dm = dm;
	}
	
	public void updateScenarioModel(ScenarioDataModel dm)
	{
		this.setScenarioModel(dm);
		if(_gf != null)
			_gf.resetAnimator(getScenarioModel().getRenderrate());
		if(_timer != null)
			_timer.setDelay(getScenarioModel().getTimeintervall());
	}
	
	private void setRecord(Record record)
	{
		_record = record;
		if(record != null)
		{
			DateFormat dateFormat = new SimpleDateFormat("dd.MM.yy HH:mm:ss");
			Date date = new Date();
			
			_record.getRecordDataModel().setRecStart(TimeStamp.generate().getValue());
			_record.getRecordDataModel().setTimeintervall(getScenarioModel().getTimeintervall());
			_record.getRecordDataModel().setSwitchName(getSwitch().getSwitchDataModel().getName());
			_record.getRecordDataModel().setSwitchAddress(getSwitch().getSwitchDataModel().getAddress() + ":" +
					getSwitch().getSwitchDataModel().getPort());
			_record.getRecordDataModel().setDate(dateFormat.format(date));
		}
	}
	
	public void openScene()
	{	
		if (logger.isInfoEnabled())
			logger.info("Visualize " + getScenarioModel().getTitle());
		_vel = new ViewEventListener(_view);
		_gf = new GraphicsFrame(getScenarioModel().getTitle(), getScenarioModel().getRenderrate(), _vel);
		_gf.setSize(1024, 768);
		_gf.addWindowListener(this);
		
		if (_replay == null)
			startSNMPRequests();
		else
			startReplay();
			
		_gf.setVisible(true);
	}
	
	public void startSNMPRequests()
	{
		if (logger.isInfoEnabled())
			logger.info("start SNMP requests with an intervall of " + getScenarioModel().getTimeintervall() + " milliseconds");
		_timer.start();
	}
	
	public void startReplay()
	{
		if (logger.isInfoEnabled())
			logger.info("start replay");
		
		_timer.setDelay(500);
		_timer.start();
	}
	
	public void closeScene()
	{
		if(_gf != null)
			_gf.setVisible(false);
		
		close();
	}
	
	
	public void actionPerformed(ActionEvent evt) 
	{
		if (_replay == null)
		{
			try 
			{
				_switch.send(_dm.isProcessSynchron());
			} 
			catch (NetworkException e) 
			{
				logger.error(e.getMessage());
			}
		}
		else
		{
			_replay.refresh();
		}
	}
	
	private void close()
	{
		if(logger.isInfoEnabled())
			logger.info("Closing scenario.");
		
		_timer.stop();
		
		if (_vel != null)
			_vel.closeDetailViews();
		
		if(_gf != null)
			_gf.stopAnimator();
		
		if (_switch != null)
		{
			try
			{
				_switch.close();
			}
			catch(NetworkException e)
			{
				logger.error("Error closing connenction.", e);
			}
		}
		
		if(getRecord() != null)
		{
			try
			{
				getRecord().getRecordDataModel().setRecEnd(TimeStamp.generate().getValue());
				getRecord().close();
			}
			catch(Exception e)
			{
				logger.error("Problems occured closing the record files. " + e.getMessage());
			}
		}
		if(_replay != null)
		{
			try 
			{
				_replay.stop();
				_replay.close();
			} 
			catch (IOException e) 
			{
				logger.error("Problems occured closing the replay files. " + e.getMessage());
			}
		}
	}

	public void windowClosed(WindowEvent evt) 
	{
		close();
	}
	
	public void windowClosing(WindowEvent evt) 
	{
		close();
	}
	
	public void windowActivated(WindowEvent arg0) {}
	public void windowDeactivated(WindowEvent arg0) {}
	public void windowDeiconified(WindowEvent arg0) {}
	public void windowIconified(WindowEvent arg0) {}
	public void windowOpened(WindowEvent arg0) {}
}
